package com.gking.processHarvest.service.Master;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gking.processHarvest.common.BaseContext;
import com.gking.processHarvest.common.Res;
import com.gking.processHarvest.entity.Master;
import com.gking.processHarvest.entity.Uploads;
import com.gking.processHarvest.mapper.MasterMapper;
import com.gking.processHarvest.service.Friends.FriendsService;
import com.gking.processHarvest.service.Uploads.UploadsService;
import com.gking.processHarvest.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Slf4j
@Service
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)//三级缓存解决bean循环注入问题
public class MasterServiceImpl extends ServiceImpl<MasterMapper, Master> implements MasterService {

    @Autowired
    private UploadsService uploadsService;

    @Autowired
    private FriendsService friendsService;


    /**
     * 用户注册
     *
     * @param account  账号
     * @param password 密码
     * @return s
     */
    @Override
    public Res<String> registerUser(String account, String password) {

        //检查账号是否被占用
        LambdaQueryWrapper<Master> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Master::getAccount, account);
        int count = this.count(lambdaQueryWrapper);
        if (count > 0) return Res.error("账号已被占用");

        //加密密码之后保存到数据库中
        String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt(10));

        Master master = new Master();
        master.setAccount(account);
        master.setPassword(hashedPassword);
        this.save(master);

        return Res.success("账号注册成功");
    }


    /**
     * 校验账号
     *
     * @param account 账号
     * @return s
     */
    @Override
    public Res<Master> verifyAccount(HttpServletRequest request, String account) {

        LambdaQueryWrapper<Master> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.eq(Master::getAccount, account);
        lambdaQueryWrapper.apply("binary account = {0}", account);
        Master user = this.getOne(lambdaQueryWrapper);
        if (user == null) return Res.error("账号不存在！");

        Master master = new Master();
        master.setAccount(user.getAccount());
        master.setAvatar(user.getAvatar());
        master.setNickname(user.getNickname());

        request.getSession().setAttribute("Master", user.getAccount());
        return Res.success("查询成功！", master);
    }


    /**
     * 登录
     *
     * @param request  request请求线程
     * @param password 密码
     * @return s
     */
    @Override
    public Res<String> loginUser(HttpServletRequest request, String password) {

        String account = (String) request.getSession().getAttribute("Master");
        log.info("从会话空间中拿到的 account： {}", account);
        //检查用户账号是否存在
        if (account == null) return Res.error("登录失败");

        LambdaQueryWrapper<Master> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.eq(Master::getAccount, account);
        lambdaQueryWrapper.apply("binary account = {0}", account);
        Master master = this.getOne(lambdaQueryWrapper);

        //检查登录密码是否正确，密码错误则返回
        boolean passwordMatch = BCrypt.checkpw(password, master.getPassword());
        log.info("密码校验是否正确： {}", passwordMatch);
        if (!passwordMatch) return Res.error("密码错误");

        //登录成功，返回登录成功结果，并清除 Session 中的用户信息
        request.getSession().removeAttribute("Master");
        JwtUtil jwtUtil = new JwtUtil();
        String token = jwtUtil.createToken(master.getId());
        log.info("生成的 token 为：{}", token);


        //shiro  框架
        Subject subject = SecurityUtils.getSubject();
        //2 封装请求数据到 token
        AuthenticationToken t = new UsernamePasswordToken(master.getId(), master.getPassword(), true);
        try {
            subject.login(t);
        } catch (AuthenticationException e) {
            e.printStackTrace();
            log.warn("shiro 登录失败！");
            return Res.error("登录失败！");
        }

        return Res.success("登录成功", token);
    }


    /**
     * 获取用户信息
     *
     * @return s
     */
    @Override
    public Res<Master> getUserInfo() {
        Master master = this.getById(BaseContext.getCurrentId());
        master.setPassword("");
        return Res.success("获取用户信息成功！", master);
    }


    /**
     * 更新用户信息
     *
     * @param desc     描述
     * @param nickname 昵称
     * @param email    email
     * @return s
     */
    @Override
    public Res<String> updateInfo(String nickname, String desc, String email) {
        String userId = BaseContext.getCurrentId();

        Master master = new Master();
        master.setId(userId);
        master.setNickname(nickname);
        master.setDescription(desc);
        master.setEmail(email);
        this.updateById(master);

        return Res.success("更新个人信息成功！");
    }


    /**
     * 修改密码
     *
     * @param oldPwd 旧密码
     * @param newPwd 新密码
     * @return s
     */
    @Override
    public Res<String> modifyPassword(String oldPwd, String newPwd) {
        if (oldPwd == null || newPwd == null) return Res.error("请将参数补充完整！");

        //查询账号是否存在
        LambdaQueryWrapper<Master> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Master::getId, BaseContext.getCurrentId());
        Master master = this.getOne(queryWrapper);
        if (master == null) return Res.error("没有查询到该账号信息！");

        //先校验旧密码
        boolean passwordMatch = BCrypt.checkpw(oldPwd, master.getPassword());
        if (!passwordMatch) return Res.error("旧密码校验错误");
        //校验成功，加密新密码之后保存到数据库中
        String hashedPassword = BCrypt.hashpw(newPwd, BCrypt.gensalt(10));
        master.setPassword(hashedPassword);

        this.updateById(master);

        return Res.success("修改密码成功！");
    }


    /**
     * 上传头像
     *
     * @param file 头像文件
     * @return s
     */
    @Override
    public Res<String> updataAvatar(Uploads file) {
        file.setMasterId(BaseContext.getCurrentId());
        //保存上传文件记录
        uploadsService.save(file);

        LambdaUpdateWrapper<Master> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Master::getId, BaseContext.getCurrentId());
        wrapper.set(Master::getAvatar, file.getPath());
        this.update(wrapper);

        return Res.success("上传头像成功");
    }
//    public Res<String> updataAvatar(MultipartFile file) {
//
//        //设置文件保存在服务器中的路径
//        String targetPath = "/src/main/resources/public/image/";
//
//        UploadFile uploadFile = new UploadFile();
//        Uploads uploads = uploadFile.uploadFile(file, targetPath);
//        if (uploads == null) return Res.error("上传头像失败");
//        //保存上传文件记录
//        uploadsService.save(uploads);
//
//        LambdaUpdateWrapper<Master> wrapper = new LambdaUpdateWrapper<>();
//        wrapper.eq(Master::getId, BaseContext.getCurrentId());
//        wrapper.set(Master::getAvatar, uploads.getPath());
//        this.update(wrapper);
//
//        return Res.success("上传头像成功");
//    }


    /**
     * 下载头像文件
     *
     * @param path 头像图片路径
     * @return s
     */
    @Override
    public Res<String> downloadFile(String path) {

        //查询是否有此头像文件
        LambdaQueryWrapper<Master> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Master::getAvatar, path);
        if (this.getOne(wrapper) == null) return Res.error("没有此头像文件");

        //获取服务器根路径
        String rootPath = System.getProperty("user.dir");
        try {
            File file = new File(rootPath + path);
            FileInputStream fileInputStream = new FileInputStream(file);

            byte[] imageData = new byte[(int) file.length()];
            fileInputStream.read(imageData);
            fileInputStream.close();

            byte[] base64Data = Base64.getEncoder().encode(imageData);
            String s = new String(base64Data, StandardCharsets.UTF_8);
            return Res.success("获取图片数据成功", s);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
